package org.fastiot.protocol.group.automotive

import grails.databinding.BindUsing
import org.fastiot.protocol.codec.BitOutputStream
import org.fastiot.protocol.codec.BitSource
import org.fastiot.protocol.group.Groupable

/**
 * 控制器局域网络（专用）单元
 */
class CtrlAreaNet implements Groupable {

    static enum Type {
        Standard(0), Extended(1)
        final int value

        private Type(int value) { this.value = value }

        static Type byValue(int val) {
            values().find { it.value == val } ?:
                    { throw new IllegalArgumentException("CtrlAreaNet\$Type ${val} not found") }()
        }
    }

    static enum Mode {
        Single(0), Multiple(1)
        final int value

        private Mode(int value) { this.value = value }

        static Type byValue(int val) {
            values().find { it.value == val } ?:
                    { throw new IllegalArgumentException("CtrlAreaNet\$Mode ${val} not found") }()
        }
    }

    /**
     * （帧）类型，标准帧/扩展帧
     */
    @BindUsing({ obj, source ->
        Type.byValue(Integer.parseInt(source["type"] as String))
    })
    Type type

    /**
     * 发送模式，单包/多包
     */
    @BindUsing({ obj, source ->
        Mode.byValue(Integer.parseInt(source["mode"] as String))
    })
    Mode mode

    Integer canId
    String hexCanId

    /**
     * 内置单元类型
     */
    @BindUsing({ obj, source ->
        Groupable.Type.byValue(Integer.parseInt(source["embeddedGroupType"] as String))
    })
    Groupable.Type embeddedGroupType
    /**
     * 内置单元隶属代码
     * 采用非持久化字段，同步canId，保持多种编组单元风格统一。
     */
    Integer embeddedGroupAffiliatedCode

    boolean enabled = false

    String remark
    Date dateCreated
    Date lastUpdated

    static embedded = ['type', 'mode']
    static transients = ['hexCanId', 'embeddedGroupAffiliatedCode']

    static constraints = {
        type(nullable: false)
        mode(nullable: false)
        canId(nullable: false, min: 0)
        hexCanId(blank: false, matches: /[a-fA-F0-9]+/)
        embeddedGroupType(nullable: false, inList: Groupable.Type.values().toList())
        embeddedGroupAffiliatedCode(nullable: true, min: 0)
        enabled(blank: false)
        remark(nullable: true, widget: 'textarea')
    }

    static mapping = {
        remark type: 'text'
    }

    def beforeValidate() {
        if (hexCanId && !canId)
            canId = Integer.parseInt(hexCanId, 16)

        if(!embeddedGroupAffiliatedCode && canId)
            embeddedGroupAffiliatedCode = canId
    }

    def afterLoad() {
        if (canId)
            hexCanId = Integer.toHexString(canId)

        embeddedGroupAffiliatedCode = canId
    }

    @Override
    void decode(BitSource bitSource, Map contents) {
        throw new UnsupportedOperationException("The method is not implemented")
    }

    @Override
    void encode(BitOutputStream bitOutput, Map contents) {
        throw new UnsupportedOperationException("The method is not implemented")
    }
}
